# encoding: UTF-8
__author__ = 'wyy'

from xml.etree import ElementTree as ET
import os
import sys
import re
import hashlib
import datetime

reload(sys)
sys.setdefaultencoding('utf8')

pattern = re.compile(r'([0-9a-zA-Z]+Bean)')
patternList = re.compile(r'List<(.*?)>')


def gen(xmlPath):
    '''
    生成协议描述
    '''

    if not os.path.exists(xmlPath):
        print "file not fount"
        exit(1)

    bodyHtml = ''
    treeHtml = ''
    methods  = []
    methodContents = []
    list     = os.listdir(xmlPath)
    packages = []

    for file in list:
        if file.endswith('xml'):
            document    = ET.parse(xmlPath + file)
            root        = document.getroot()
            comment     = root.attrib['comment']
            controller  = root.attrib['package']

            if root.attrib.has_key('implname'):
                implname = root.attrib['implname']
            else:
                implname = controller

            packages.append(controller)

            beans       = processBeans(root)
            protocols   = processProtocols(root)
            bodyHtml    += html(beans, protocols, controller)
            treeHtml    += tree(comment, protocols, beans)
            ms          = createJsMethodNames(protocols, controller)
            methods     = methods + ms
            mscontent   = createJsMethod(protocols, controller)
            methodContents = methodContents + mscontent

            #生成JAVA Bean
            createJavaBeans(beans)

    # 生成JAVA JFinal  Control 层代码
    createJFinalControl(list, xmlPath)

    #生成协议描述文件
    template        = open('html/template.html', 'r')
    htmlFile        = open('html/protocols.html', 'w')
    for line in template:
        if line.strip() == '#{tree}':
            line = treeHtml
        if line.strip() == '#{body}':
            line = bodyHtml
        htmlFile.writelines(line)

    #生成JS 请求就接口
    createJsNetFile(methods, methodContents)


def tree(comment, protocols, beans):
    content = '<li class="cur">'
    content += '<a href="#" class="one">' + comment + '</a>'
    content += '<ul>'
    for key in protocols:
        m       = hashlib.md5()
        method  = protocols[key]['method']
        m.update(method)
        urlmd5 = m.hexdigest()
        content += '<li><a href="#'+ urlmd5 + '">' + protocols[key]['method'] + '(' + protocols[key]['comment'] + ')' + '</a></li>'
    content += '</ul>'
    content += '</li>'

    for key in beans:
        content += '<li><a href="#'+ key + '">' + key + '</a></li>'

    return content

def html(beans, protocols, controller):
    '''
    生成接口描述
    :param beans:
    :param protocols:
    :return:
    '''

    htmlContent = ''
    for key  in protocols:
        protocol = protocols[key]
        htmlContent += protocolHtml(protocol, controller)

    for key in beans:
        bean = beans[key]
        htmlContent += beanHtml(bean)

    return htmlContent

def beanHtml(bean):
    '''
    生成Bean的描述文件
    :param bean:
    :return:
    '''
    html = '<div id="' + bean['name'] + '">'
    html += '<table>'
    html += '<tr>'
    html += '<th colspan="3">Bean名称:' + bean['name']
    if bean.has_key('extends') and bean['extends']:
        html += '&nbsp;&nbsp;&nbsp;&nbsp;继承自:<a href="#' + bean['extends'] + '">' + bean['extends'] + '</a>'
    html += '</th>'
    html += '</tr>'
    html += '<tr>'
    html += '<td colspan="3">Bean描述:' + bean['comment'] + '</td>'
    html += '</tr>'
    html += '<tr>'
    html += '<td colspan="3">属性列表</td>'
    html += '</tr>'
    html += '<tr>'
    html += '<td>属性名称</td>'
    html += '<td>属性类型</td>'
    html += '<td>属性描述</td>'
    html += '</tr>'
    for param in bean['params']:
        html += '<tr>'
        html += '<td>' + param['name'] + '</td>'
        html += '<td>' + getTypeContent(param['type']) + '</td>'
        html += '<td>' + param['comment'] + '</td>'
        html += '</tr>'
    html += '</table>'
    html += '</div>\n'

    return html

def protocolHtml(protocol, controller):
    '''
    生成协议的HTML描述文件
    :param protocol:
    :return:
    '''
    m       = hashlib.md5()
    m.update(protocol['method'])
    urlMd5 = m.hexdigest()

    html = '<div id="' + urlMd5 + '">'
    html += '<table >'
    html += '<tr>'
    html += '<th colspan="3">接口名称:' + controller + '_' + protocol['method'] + '</th>'
    html += '</tr>'
    html += '<tr>'
    html += '<td colspan="3">接口描述:' + protocol['comment'] + '</td>'
    html += '</tr>'
    html += '<tr>'
    html += '<td colspan="3">参数列表:</td>'
    html += '</tr>'
    html += '<tr>'
    html += '<td>参数名称</td><td>参数类型</td><td>参数描述</td>'
    html += '</tr>'

    for param in protocol['params']:
        html += '<tr>'
        html += '<td>'
        html += param['name']
        html += '</td>'
        html += '<td>'
        html += getTypeContent(param['type'])
        html += '</td>'
        html += '<td>'
        html += param['comment']
        html += '</td>'
        html += '</tr>'

    html += '<tr><td colspan="3">返回内容:' + getTypeContent(protocol['return'])  + '</td></tr>'

    demos = []
    for param in protocol['params']:
        demoVal = param['demoVal']
        if (param['type'] == 'Integer'):
            demos.append(demoVal)
        else:

            #demoVal = demoVal.replace('"', "\"");
            demos.append('"' + demoVal + '"')

    s = ','
    html += '<tr><td colspan="3">JAVA DEMO:client.invoke("' + controller + '_' + protocol['method'] + '", new Object[]{' + s.join(demos) + '}));</td></tr>';
    html += '</table>'
    html += '</div>\n'
    return html

def getTypeContent(type):
    m = pattern.search(type)
    if m:
        bean = m.group(1)
        type = type.replace(bean, '<a href="#' + bean + '">' + bean + '</a>')
        return type
    else:
        mL = patternList.search(type)
        if mL:
            type = 'List<<a>'+mL.group(1)+'</a>>'
        return type


def processBeans(root):
    '''
    处理Beans
    :return:
    '''
    beanElements    = root.findall('bean')
    beans           = {}

    if beanElements:
        for element in beanElements:
            attr = element.attrib
            name = attr['name']
            if beans.has_key(name):
                print name + ' 已经存在，生成失败'
                exit(2)
            extends = '';
            if attr.has_key('extends'):
                extends = attr['extends']
            bean = {'name':name, 'comment':attr['comment'], 'extends':extends, 'params':getParams(element)}
            beans[name] = bean

    return beans

def processProtocols(root):
    '''
    处理协议
    :param root:
    :return:
    '''
    protoclElements = root.findall('protocl')
    protocls        = {}
    if protoclElements:
        for element in protoclElements:
            attr    = element.attrib
            method  = attr['method']
            if protocls.has_key(method):
                print method + ' 方法已存在'
                exit(3)

            protocl          = {'method':method, 'return':attr['return'], 'comment':attr['comment'], 'params':getParams(element)}
            if attr.has_key('complete'):
                protocl['complete'] = attr['complete']
            else:
                protocl['complete'] = '0';
            protocls[method] = protocl
        return protocls;
    else:
        return protocls

def getParams(element):
    '''
    获取参数
    :param element:
    :return:
    '''

    paramElements = element.findall('param')
    params = []

    if paramElements:
        for ele in paramElements:
            attr = ele.attrib;
            if attr.has_key('demoVal'):
                params.append({'name':attr['name'], 'type':attr['type'], 'demoVal':attr['demoVal'], 'comment':attr['comment']})
            else:
                params.append({'name':attr['name'], 'type':attr['type'], 'demoVal':'', 'comment':attr['comment']})
        return  params
    else:
        return params

def createHproseControl(package, comment, protocols,implname):
    controlPackage      = 'com.aibei.hprose.control'
    appDir              = getAppDir();
    hproseControlDir    = appDir + '/src/' + controlPackage.replace('.', '/') + '/'

    javaFileContent     =  'package ' + controlPackage + ';\n'
    javaFileContent     += 'import com.aibei.control.bean.*;\n'
    javaFileContent     += 'import com.jfinal.aop.Duang;\n';
    javaFileContent     += 'import java.util.*;\n'
    javaFileContent     += '/**\n'
    javaFileContent     += '*' + comment + '\n'
    javaFileContent     += '*/\n'
    javaFileContent     += 'public class ' + package + '{\n'
    javaFileContent     += '\tcom.aibei.control.' + implname + ' ' + getName(package) + ' = Duang.duang(new com.aibei.control.' + implname + '());\n'

    for key in protocols:
        protocol = protocols[key]
        #生成注释
        javaFileContent     += '\t/**\n'
        javaFileContent     += '\t*' + protocol['comment'] + '\n'
        for param in protocol['params']:
            javaFileContent     += '\t* param:' + param['name'] + ' type:' + param['type'] +' 描述:' + param['comment'] + '\n'
        javaFileContent     += '\t*/\n'

        #生成方法
        javaFileContent     += '\tpublic ControllerResultBean ' + protocol['method'] + '('
        javaParamsDif       = []
        javaParams          = []
        for param in protocol['params']:
            javaParamsDif.append(param['type'] + ' ' + param['name'])
            javaParams.append(param['name'])
        javaFileContent     += ', '.join(javaParamsDif) + '){\n'

        #生成方法内容
        javaFileContent     += '\t\t return ' + getName(package) + '.' + protocol['method'] + '(' + ", ".join(javaParams) + ');\n'
        javaFileContent     += '\t}\n\n'

    javaFileContent += '}'


    javaFile = open(hproseControlDir + package + '.java', 'w')
    javaFile.writelines(javaFileContent)

def createJFinalControl(fileList, xmlPath):
    appDir              = getAppDir();
    controlPackage      = "com.ayez.control";
    hproseControlDir    = appDir + '/src/' + controlPackage.replace('.', '/') + '/'

    fileContent = "package com.ayez.control;\n"
    fileContent += "\n"
    fileContent += "import java.lang.reflect.Method;\n"
    fileContent += "import java.util.ArrayList;\n"
    fileContent += "import java.util.HashMap;\n"
    fileContent += "import java.util.List;\n"
    fileContent += "import java.util.Map;\n"
    fileContent += "import com.ayez.util.ErrorConstant;\n"
    fileContent += "import com.alibaba.fastjson.JSON;\n"
    fileContent += "import com.alibaba.fastjson.JSONArray;\n"
    fileContent += "import com.jfinal.core.Controller;\n"
    fileContent += "import com.ayez.control.beans.*;\n"
    fileContent += "import com.ayez.control.impl.*;\n"
    fileContent += "import com.ayez.tools.LogUtil;\n"
    fileContent += "import com.jfinal.plugin.redis.Redis;\n"
    fileContent += "import com.ayez.model.Account;\n"
    fileContent += "import com.ayez.service.ThreadPoolService;\n"
    fileContent += "import com.ayez.service.ServiceFactory;\n"
    fileContent += "import com.ayez.service.IntegralService;\n"


    fileContent += "\n"
    fileContent += "public class DispatchControl extends Controller {\n"
    fileContent += "\n"
    fileContent += "\tprivate static final Map<String, MethodInfo> METHODS = new HashMap<>();\n"
    fileContent += "\tprivate static final Map<String, Method> PARAMS_METHODS = new HashMap<>();\n"
    fileContent += "\tprivate static final Map<String, String[]> PROTOCL_NAME = new HashMap<>();\n";

    impls = []

    getParamsMethodContent = ""
    
    getPreValidationStaticContent = ""
    getPreValidationMethodContent = ""
    getPreValidationMethodContent +="\tprivate ResultBean preValidationMethod(String name,Object[] pString) {\n"

    for file in fileList:
        if file.endswith('xml'):
            document = ET.parse(xmlPath + file)
            root = document.getroot()
            comment = root.attrib['comment']
            controller = root.attrib['package']

            if root.attrib.has_key('implname'):
                implname = root.attrib['implname']
            else:
                implname = controller

            impls.append(implname)

            beans = processBeans(root)
            protocols = processProtocols(root)
            createJavaBeans(beans)

            #创建接口和实例
            createControlInterface(implname, protocols)
            createControlImp(implname, protocols)


            #生成获取方法参数
            for key in protocols:
                protocol = protocols[key]
                getParamsMethodContent += "\tprivate Object[] get" + implname + "_" + protocol["method"] + "Params(String params){\n"
                getParamsMethodContent += "\t\tJSONArray array = JSON.parseArray(params);\n"
                getParamsMethodContent += "\t\tObject[] paramArray = new Object[array.size()];\n";
                
                getPreValidationStaticContent += "\t\tString[] paramsIn" + protocol["method"] +  " = {"
                for i in range(0, len(protocol['params'])):
                    
                    param = protocol['params'][i]
                    getPreValidationStaticContent += "\"" + param['name'] + "\""
                    if i < len(protocol['params'])-1:
                        getPreValidationStaticContent += ","
                    i = str(i)
                    paramType = param['type']
                    if paramType == "int" or paramType == "Integer":
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getInteger(" + i + ");\n"
                    elif paramType == "long" or paramType == "Long":
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getLong(" + i + ");\n"
                    elif paramType == "float" or paramType == "Float":
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getFloat(" + i + ");\n"
                    elif paramType == "boolean" or paramType == "Boolean":
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getBoolean(" + i + ");\n"
                    elif paramType.startswith("list") or paramType.startswith("List"):
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getJSONArray(" + i + ").toJavaList(" + paramType[5:-1] + ".class);\n"
                    elif paramType.startswith("map") or paramType == "Map":
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getJSONObject(" + i + ");\n"
                    elif paramType == "String":
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getString(" + i + ");\n"
                    else:
                        getParamsMethodContent += "\t\tparamArray[" + i + "] = array.getObject(" + i + "," + paramType + ".class);\n"
            
                getPreValidationStaticContent += "};\n"
                getPreValidationStaticContent += "\t\tPROTOCL_NAME.put(\"" + implname + "_" + protocol["method"] +"\", paramsIn" + protocol["method"] + ");\n"
                getParamsMethodContent  += "\t\treturn paramArray;\n"
                getParamsMethodContent += "\t}\n"

    getPreValidationMethodContent += "\t\tString[] paramsString = PROTOCL_NAME.get(name);\n"
    getPreValidationMethodContent += "\t\tfor (int i = 0; i < pString.length; i++) {\n"
    getPreValidationMethodContent += "\t\t\tif (paramsString[i].equals(\"token\")) {\n"
    getPreValidationMethodContent += "\t\t\t\tString cacheKey = \"ACCOUNT_TOKEN_\"+pString[i];\n"
    getPreValidationMethodContent += "\t\t\t\tAccount account = Redis.use().get(cacheKey);\n"
    getPreValidationMethodContent += "\t\t\t\tif (account == null) {\n"
    getPreValidationMethodContent += "\t\t\t\t\treturn ErrorConstant.ERROR_TOKEN;\n"
    getPreValidationMethodContent += "\t\t\t\t}\n"
    getPreValidationMethodContent += "\t\t\t}\n"
    getPreValidationMethodContent += "\t\t\tif (pString[i] == null) {\n"
    getPreValidationMethodContent += "\t\t\t\treturn ErrorConstant.ERROR_PARAMS;\n"
    getPreValidationMethodContent += "\t\t\t\t}\n"
    getPreValidationMethodContent += "\t\t\t}\n"
    getPreValidationMethodContent += "\t\t\treturn null;\n"
    getPreValidationMethodContent += "\t};\n"


    initMethodContent = "\tpublic static void init(){\n"
    initMethodContent += "\t\tList<Class<?>> controlList = new ArrayList<>();\n"
    for impl in impls:
        initMethodContent += "\t\tcontrolList.add(" + impl + "Impl.class);\n"
    initMethodContent += "\t\tfor (Class<?> c: controlList){\n"
    initMethodContent += "\t\t\ttry{\n"
    initMethodContent += "\t\t\t\tObject install = c.newInstance();\n"
    initMethodContent += "\t\t\t\tMethod[] methods = c.getDeclaredMethods();\n"
    initMethodContent += "\t\t\t\tfor (Method m: methods){\n"
    initMethodContent += "\t\t\t\t\tString key = c.getSimpleName().substring(0, c.getSimpleName().length() - 4) + \"_\" + m.getName();\n"
    initMethodContent += "\t\t\t\t\tMethodInfo info = new MethodInfo(key, m, install);\n"
    initMethodContent += "\t\t\t\t\tMETHODS.put(key, info);\n"
    initMethodContent += "\t\t\t\t}\n"
    initMethodContent += "\t\t\t}catch(Exception e){}\n"
    initMethodContent += "\t\t}\n"
    initMethodContent += "\t\tfor (Method m: DispatchControl.class.getDeclaredMethods()){\n"
    initMethodContent += "\t\t\tif (m.getName().startsWith(\"get\") && m.getName().endsWith(\"Params\")){\n"
    initMethodContent += "\t\t\t\tPARAMS_METHODS.put(m.getName(), m);\n"
    initMethodContent += "\t\t\t}\n"
    initMethodContent += "\t\t}\n"
    initMethodContent += getPreValidationStaticContent
    initMethodContent += "\t}\n"

    fileContent += initMethodContent
    fileContent += "\tpublic void index(){\n"
    fileContent += "\t\tString origin = this.getRequest().getHeader(\"Origin\");\n"
    fileContent += "\t\tthis.getResponse().setHeader(\"Access-Control-Allow-Origin\", origin);\n"
    fileContent += "\t\tthis.getResponse().setHeader(\"Access-Control-Allow-Credentials\", Boolean.TRUE.toString());\n"
    fileContent += "\t\tInteger startTime = (int)(System.currentTimeMillis()/1000);\n"
    fileContent += "\t\tString mName 	= this.getPara(\"method\");\n"
    fileContent += "\t\tString mParams 	= this.getPara(\"mParams\");\n"
    fileContent += "\t\tMethodInfo info = METHODS.get(mName);\n"
    fileContent += "\t\tif (info == null){\n"
    fileContent += "\t\t\tthis.renderJson(ErrorConstant.ERROR_PARAMS);\n"
    fileContent += "\t\t\tInteger endTime = (int)(System.currentTimeMillis()/1000);\n"
    fileContent += "\t\t\tStringBuilder stringBuilder = new StringBuilder();\n"
    fileContent += "\t\t\tstringBuilder.append(mName).append(\"  \").append(mParams).append(\"  \").append(endTime-startTime).append(\"  \").append(JSON.toJSONString(ErrorConstant.ERROR_PARAMS));\n"
    fileContent += "\t\t\tLogUtil.debug(stringBuilder.toString());\n"
    fileContent += "\t\t\treturn;\n"
    fileContent += "\t\t}\n"
    fileContent += "\t\tMethod pM = PARAMS_METHODS.get(\"get\" + mName + \"Params\");\n"
    fileContent += "\t\tif (pM == null){\n"
    fileContent += "\t\t\tthis.renderJson(ErrorConstant.ERROR_SERVER);\n"
    fileContent += "\t\t\tInteger endTime = (int)(System.currentTimeMillis()/1000);\n"
    fileContent += "\t\t\tStringBuilder stringBuilder = new StringBuilder();\n"
    fileContent += "\t\t\tstringBuilder.append(mName).append(\"  \").append(mParams).append(\"  \").append(endTime-startTime).append(\"  \").append(JSON.toJSONString(ErrorConstant.ERROR_SERVER));\n"
    fileContent += "\t\t\tLogUtil.debug(stringBuilder.toString());\n"
    fileContent += "\t\t\treturn;\n"
    fileContent += "\t\t}\n"

    fileContent += "\t\ttry{\n"
    fileContent += "\t\t\tObject[] params = (Object[])pM.invoke(this, mParams);\n"

    fileContent += "\t\t\tObject result = info.m.invoke(info.obj, params);\n"
    fileContent += "\t\t\tthis.renderJson(result);\n"
    fileContent += "\t\t\tInteger endTime = (int)(System.currentTimeMillis()/1000);\n"
    fileContent += "\t\t\tStringBuilder stringBuilder = new StringBuilder();\n"
    fileContent += "\t\t\tstringBuilder.append(mName).append(\"  \").append(mParams).append(\"  \").append(endTime-startTime).append(\"  \").append(JSON.toJSONString(result));\n"
    fileContent += "\t\t\tLogUtil.debug(stringBuilder.toString());\n"
    fileContent += "\t\t\tThreadPoolService pService = ServiceFactory.getService(ThreadPoolService.class);\n"
    fileContent += "\t\t\tpService.execute(()->{\n"
    fileContent += "\t\t\t\tIntegralService integralService = ServiceFactory.getService(IntegralService.class);\n"
    fileContent += "\t\t\t\tintegralService.event(mName, params, PROTOCL_NAME.get(mName));\n"
    fileContent += "\t\t\t});\n"
    fileContent += "\t\t}catch(Exception e){\n"
    fileContent += "\t\t\tthis.renderJson(ErrorConstant.ERROR_SERVER);\n"
    fileContent += "\t\t\tInteger endTime = (int)(System.currentTimeMillis()/1000);\n"
    fileContent += "\t\t\tStringBuilder stringBuilder = new StringBuilder();\n"
    fileContent += "\t\t\tstringBuilder.append(mName).append(\"  \").append(mParams).append(\"  \").append(endTime-startTime).append(\"  \").append(JSON.toJSONString(ErrorConstant.ERROR_SERVER));\n"
    fileContent += "\t\t\tLogUtil.sysError(stringBuilder.toString(), e);\n"
    fileContent += "\t\t}\n"
    fileContent += "\t\treturn;\n"
    fileContent += "\t}\n"

    fileContent += getParamsMethodContent

    fileContent += getPreValidationMethodContent

    fileContent += "\tprivate static class MethodInfo{\n"
    fileContent += "\t\tpublic MethodInfo(String key, Method m, Object obj){\n"
    fileContent += "\t\t\tthis.key = key;\n"
    fileContent += "\t\t\tthis.m = m;\n"
    fileContent += "\t\t\tthis.obj = obj;\n"
    fileContent += "\t\t}\n"
    fileContent += "\t\tpublic Method m;\n"
    fileContent += "\t\tpublic String key;\n"
    fileContent += "\t\tpublic Object obj;\n"
    fileContent += "\t}\n"
    fileContent += "}\n"

    javaFile = open(hproseControlDir + 'DispatchControl.java', 'w')
    javaFile.writelines(fileContent)
    javaFile.close()

def createControlInterface(name, protocols):
    pack = "com.ayez.control"
    fileContent = "package com.ayez.control;\n"
    fileContent += "import com.ayez.control.beans.*;\n"
    fileContent += "import java.util.List;\n"
    fileContent += "public interface I" + name + " {\n"
    for pk in protocols:
        p = protocols[pk]
        fileContent += "\t/**\n"
        fileContent += "\t *" + p['comment'] + "\n"
        fileContent += "\t*/\n"
        fileContent += "\tpublic ResultBean " + p['method'] + "("
        paramArr = []
        for param in p['params']:
            paramArr.append(param['type'] + " " + param['name'])
        fileContent += ",".join(paramArr) + ");\n"
    fileContent += "}\n"

    appDir = getAppDir();
    outDir = appDir + '/src/' + pack.replace('.', '/') + '/'
    javaFile = open(outDir + "I" + name + ".java" , 'w')
    javaFile.writelines(fileContent)
    javaFile.close()

def createControlImp(name, protocols):
    pack = "com.ayez.control.impl"

    appDir = getAppDir();
    outDir = appDir + '/src/' + pack.replace('.', '/') + '/' + name + "Impl.java"
    if (os.path.exists(outDir)):
        return


    fileContent = "package com.ayez.control.impl;\n"
    fileContent += "import com.ayez.control.beans.*;\n"
    fileContent += "import com.ayez.control.*;\n"
    fileContent += "public class " + name + "Impl implements I" + name + " {\n"
    for pk in protocols:
        p = protocols[pk]
        fileContent += "\t/**\n"
        fileContent += "\t *" + p['comment'] + "\n"
        fileContent += "\t*/\n"
        fileContent += "\tpublic ResultBean " + p['method'] + "("
        paramArr = []
        for param in p['params']:
            paramArr.append(param['type'] + " " + param['name'])
        fileContent += ",".join(paramArr) + "){\n"
        fileContent += "\t\t//do something\n"
        fileContent += "\t\treturn null;\n"
        fileContent += "\t}\n"
    fileContent += "}\n"


    javaFile = open(outDir, 'w')
    javaFile.writelines(fileContent)
    javaFile.close()

def createJavaBeans(beans):
    '''
    创建JAVA Bean
    :return:
    '''
    package = 'com.ayez.control.beans'
    appDir  = getAppDir();
    beanDir = appDir + '/src/' + package.replace('.', '/') + '/'


    for key in beans:
        fileContent = 'package com.ayez.control.beans;\n\n'
        fileContent += 'import java.util.*;\n\n'
        bean = beans[key]
        fileContent += '/**\n'
        fileContent += '*' + bean['comment'] + '\n'
        fileContent += '*/\n\n'
        fileContent += 'public class ' + bean['name']
        if bean['extends']:
            fileContent += ' extends ' + bean['extends']
        fileContent += ' {\n'

        #生成属相
        for param in bean['params']:
            fileContent += '\t//' + param['comment'] + '\n'
            fileContent += '\tprivate ' + param['type'] + ' ' + param['name'] + ';\n'
        fileContent += '\n'

        #生成GET和SET方法
        for param in bean['params']:
            fileContent += '\tpublic ' + param['type'] + ' get' + getJavaMethodName(param['name']) + '(){\n'
            fileContent += '\t\treturn ' + param['name'] + '; \n'
            fileContent += '\t}\n'
            fileContent += '\tpublic void set' + getJavaMethodName(param['name']) + '(' + param['type'] + ' ' + param['name'] + '){\n'
            fileContent += '\t\tthis.' + param['name'] + ' = ' + param['name'] + '; \n'
            fileContent += '\t}\n'

        fileContent += '}\n';
        javaFile = open(beanDir + bean['name'] + '.java', 'w')
        javaFile.writelines(fileContent)
        javaFile.close()


def createJsMethodNames(protocols, controller):
    '''
    生成JS网络层代码
    :param protocols:
    :param controller:
    :return:
    '''
    methods = [];

    # ManagerController 接口不生产JS接口
    if controller == "ManagerController":
        return methods

    for key in protocols:
        protocol = protocols[key]
        methods.append(controller + "_" + protocol['method'])
    return methods

def createJsMethod(protocols, controller):
    methodContents = []

    # ManagerController 接口不生产JS接口
    if controller == "ManagerController":
        return methodContents

    for key in protocols:
        protocol = protocols[key]
        funcName = controller + "_" + protocol['method']
        content = "\t\t" + funcName + " : function ("
        for param in protocol['params']:
            content = content + param['name'] + ", "
        content = content + 'success, faile){\n'
        content = content + '\t\t\t//' + protocol['comment'] + '\n'
        content =  content + "\t\t\tclient." + funcName + "("
        for param in protocol['params']:
            content = content + param['name'] + ", "
        content = content + "function(result){\n"
        content = content + "\t\t\t\tif(result.code != 0){\n"
        content = content + "\t\t\t\t\tfaile==undefined? defaultErrorProcessFunc(result):faile(result);\n"
        content = content + "\t\t\t\t\thiddenLoading();\n"
        content = content + "\t\t\t\t}else{\n"
        content = content + "\t\t\t\t\tsuccess(result.result);\n"
        content = content + "\t\t\t\t\thiddenLoading();\n"
        content = content + "\t\t\t\t}\n"
        content = content + "\t\t\t}"
        content = content + ",faile == undefined? defaultErrorProcessFunc:faile);\n"
        content = content + "\t\t}"
        methodContents.append(content)
    return methodContents

def createJsNetFile(methods, methodContent):
    fileContent = "/**\n"
    fileContent = fileContent + " * yuhaitao " + datetime.date.today().strftime("%Y-%m-%d") + "\n"
    fileContent = fileContent + " */\n\n"
    fileContent = fileContent + "require.config({\n"
    fileContent = fileContent + "paths:{\n"
    fileContent = fileContent + "\t\t'hprose':'../base/hprose',\n"
    fileContent = fileContent + "\t\t'config':'../logic/config'\n"
    fileContent = fileContent +"\t}\n"
    fileContent = fileContent +"});\n"
    fileContent = fileContent + "define(['hprose','config'],function (hprose,config) {\n"
    fileContent = fileContent + "\tmethods=" + '["' + '","'.join(methods) + '"]' + ";\n"
    fileContent = fileContent + "\tvar defaultErrorProcessFunc = function (error) {\n"
    fileContent = fileContent + "\t\tconfig.defaultErrorFunc(error);\n"
    fileContent = fileContent + "\t\thiddenLoading();\n"
    fileContent = fileContent + "\t}\n"
    fileContent = fileContent + '\tvar client = hprose.Client.create(config.serverUrl, methods);\n'
    fileContent = fileContent + "\treturn {\n"
    fileContent = fileContent + ",\n".join(methodContent)
    fileContent = fileContent + "\n\t}\n"
    fileContent = fileContent + "});\n"
    javaFile = open(getAppDir() + "/tools/ProtocolGen/netjs/net.js", 'w')
    javaFile.writelines(fileContent)
    pass

def getJavaMethodName(name):
    return name[0:1].upper() + name[1:]

def getName(name):
    return name[0:1].lower() + name[1:]

def getAppDir():
    return os.path.abspath('../../')

if __name__ == '__main__':
    gen('xml/')



